package com.atguigu.crowd.mvc.config;

import com.atguigu.crowd.exception.AccessForbiddenException;
import com.atguigu.crowd.exception.LoginAcctAlreadyInForUpdateUseException;
import com.atguigu.crowd.exception.LoginAcctAlreadyInUseException;
import com.atguigu.crowd.exception.LoginFailedException;
import com.atguigu.crowd.util.CrowdUtil;
import com.atguigu.crowd.util.ResultEntity;
import com.google.gson.Gson;
import com.sun.org.apache.xpath.internal.operations.Mod;
import org.springframework.http.HttpRequest;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@ControllerAdvice//表示当前这个类是一个基于注解的处理异常类
public class CrowdExceptionResolver {
    // 用户更改用户账号与其他重复的时候
    @ExceptionHandler(value = LoginAcctAlreadyInForUpdateUseException.class)
    public ModelAndView resolveArithmeticException(LoginAcctAlreadyInForUpdateUseException exception,
                                                   HttpServletRequest request,
                                                   HttpServletResponse response)throws IOException{
        String viewName = "system-error";
        return commonResolve(viewName, exception, request, response);

    }


    // 新增管理员时，login_acct已存在，则返回admin-add.jsp页面
    @ExceptionHandler(value = LoginAcctAlreadyInUseException.class)
    public ModelAndView resolveArithmeticException(LoginAcctAlreadyInUseException exception,
                                                   HttpServletRequest request,
                                                   HttpServletResponse response)throws IOException{
        String viewName = "admin-add";
        return commonResolve(viewName, exception, request, response);

    }
    @ExceptionHandler(value = Exception.class)
    public ModelAndView resolveAccessForbiddenException(
            Exception exception,
            HttpServletRequest request,
            HttpServletResponse response
    ) throws IOException {
        String viewName = "admin-login";
        return commonResolve(viewName, exception, request, response);
    }

//    @ExceptionHandler(value = Exception.class)
//    public ModelAndView resolveException(
//            Exception exception,
//            HttpServletRequest request,
//            HttpServletResponse response
//    ) throws IOException {
//        String viewName = "system-error";
//        return commonResolve(viewName, exception, request, response);
//    }


// 触发登录失败异常，则继续返回登陆页面
    @ExceptionHandler(value = LoginFailedException.class)
    public ModelAndView resolveLoginFailedException(LoginFailedException exception,
                                                    HttpServletResponse response,
                                                    HttpServletRequest request) throws IOException {
        String viewName="admin-login";

        return commonResolve(viewName,exception,request,response);
    }
//    空指针异常的处理方式

    @ExceptionHandler(value = NullPointerException.class)
    public ModelAndView resolveNullPointerException(
            NullPointerException exception,
            HttpServletRequest request,
            HttpServletResponse response) throws IOException {

        String viewName = "system-error";

        return commonResolve(viewName, exception, request, response);
    }


    private ModelAndView commonResolve(

            // 异常处理完成后要去的页面
            String viewName,

            // 实际捕获到的异常类型
            Exception exception,

            // 当前请求对象
            HttpServletRequest request,

            // 当前响应对象
            HttpServletResponse response) throws IOException {

        // 1.判断当前请求类型
        boolean judgeResult = CrowdUtil.judgeRequestType(request);

        // 2.如果是Ajax请求
        if (judgeResult) {

            // 3.创建ResultEntity对象
            ResultEntity<Object> resultEntity = ResultEntity.failed(exception.getMessage());

            // 4.创建Gson对象
            Gson gson = new Gson();

            // 5.将ResultEntity对象转换为JSON字符串
            String json = gson.toJson(resultEntity);

            // 6.将JSON字符串作为响应体返回给浏览器
            response.getWriter().write(json);

            // 7.由于上面已经通过原生的response对象返回了响应，所以不提供ModelAndView对象
            return null;
        }

        // 8.如果不是Ajax请求则创建ModelAndView对象
        ModelAndView modelAndView = new ModelAndView();

        // 9.将Exception对象存入模型
        modelAndView.addObject("exception", exception);

        // 10.设置对应的视图名称
        modelAndView.setViewName(viewName);

        // 11.返回modelAndView对象
        return modelAndView;
    }
}
